package com.alibaba.dcm.tool; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.io.FileUtils; import java.io.File; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Scanner; import static java.lang.System.exit; /** * @author Jerry Lee (oldratlee at gmail dot com) * @since 1.4.0 */ public class DcmTool { static final String DCM_AGENT_SUCCESS_MARK_LINE = "!!DCM SUCCESS!!"; static final String DCM_TOOLS_TMP_FILE = "DCM_TOOLS_TMP_FILE"; static final String DCM_TOOLS_AGENT_JAR = "DCM_TOOLS_AGENT_JAR"; static List<String> actionList = new ArrayList<String>(); static { actionList.add("set"); actionList.add("get"); actionList.add("rm"); actionList.add("list"); actionList.add("clear"); actionList.add("setPolicy"); actionList.add("getPolicy"); actionList.add("setNegativePolicy"); actionList.add("getNegativePolicy"); } public static void main(String[] args) throws Exception { final String tmpFile = getConfig(DCM_TOOLS_TMP_FILE); final String agentJar = getConfig(DCM_TOOLS_AGENT_JAR); if (tmpFile == null || tmpFile.trim().isEmpty() || agentJar == null || agentJar.trim().isEmpty()) { throw new IllegalStateException("blank tmp file " + tmpFile + ", or blank agent jar file " + agentJar); } final Options options = new Options(); options.addOption("p", "pid", true, "java process id to attach"); options.addOption("h", "help", false, "show help"); CommandLineParser parser = new DefaultParser(); CommandLine cmd = parser.parse(options, args); if (cmd.hasOption('h')) { HelpFormatter hf = new HelpFormatter(); hf.printHelp("Options", options); return; } final String[] arguments = cmd.getArgs(); if (arguments.length < 1) { System.out.println("No Action! Available action: " + actionList); exit(2); } final String action = arguments[0].trim(); if (!actionList.contains(action)) { throw new IllegalStateException("Unknown action " + action + ". Available action: " + actionList); } final String pid; if (cmd.hasOption('p')) { pid = cmd.getOptionValue('p'); } else { pid = selectProcess(); } StringBuilder agentArgument = new StringBuilder(); agentArgument.append(action); for (int i = 1; i < arguments.length; i++) { String s = arguments[i]; agentArgument.append(' ').append(s); } agentArgument.append(" file ").append(tmpFile); VirtualMachine vm = null; // target java process pid boolean actionSuccess = false; try { vm = VirtualMachine.attach(pid); vm.loadAgent(agentJar, agentArgument.toString()); // loadAgent method will wait to agentmain finished. final List<String> lines = FileUtils.readLines(new File(tmpFile), "UTF-8"); final int lastIdx = lines.size() - 1; final String lastLine = lines.get(lastIdx); if (DCM_AGENT_SUCCESS_MARK_LINE.equals(lastLine)) { lines.remove(lastIdx); actionSuccess = true; } for (String line : lines) { System.out.println(line); } } finally { if (null != vm) { vm.detach(); } } if (!actionSuccess) { exit(1); } } static String getConfig(String name) { String var = System.getProperty(name); if (var == null) { var = System.getenv(name); } return var; } static String selectProcess() { System.out.println("Which java process to attache:"); final List<VirtualMachineDescriptor> list = VirtualMachine.list(); // remove current process for (Iterator<VirtualMachineDescriptor> iterator = list.iterator(); iterator.hasNext(); ) { VirtualMachineDescriptor vm = iterator.next(); if (vm.id().equals(pid())) iterator.remove(); } for (int i = 0; i < list.size(); i++) { final VirtualMachineDescriptor vm = list.get(i); System.out.printf("%d) %-5s %s\n", i + 1, vm.id(), vm.displayName()); } Scanner in = new Scanner(System.in); while (true) { System.out.print("?# "); final String select = in.nextLine(); try { final int idx = Integer.parseInt(select); if (idx > 0 && idx <= list.size()) { return list.get(idx - 1).id(); } System.out.println("Invalid selection!"); } catch (NumberFormatException e) { System.out.println("Invalid input, not number!"); } } } static String pid() { final String name = ManagementFactory.getRuntimeMXBean().getName(); final int idx = name.indexOf("@"); return name.substring(0, idx); } }